﻿using System;
using System.IO;
using System.Text;
using LoungeRepo.Contracts.EntityStore;
using LoungeRepo.EntityStore;
using NUnit.Framework;

namespace Test.LoungeRepo.EntityStore
{
    [TestFixture]
    public class testFileSystemEntityStore
    {
        private class MockStreamedStringAsEntity : IStreamedEntity
        {
            #region Implementation of IStreamedEntity

            public string Id
            {
                get { return "myid"; }
            }

            public string Partition
            {
                get { return "mypartition"; }
            }

            public Stream Blob
            {
                get { return new MemoryStream(Encoding.Default.GetBytes("hello, world!")); }
            }

            #endregion
        }


        [Test]
        public void Store_in_mem_stream()
        {
            var sut = new FilesystemEntityStore("testrepo");
            var mock = new MockStreamedStringAsEntity();
            var mem = new MemoryStream();

            sut.Store(mem, mock);

            Assert.AreEqual(mock.Blob.Length, mem.Length);
        }


        [Test]
        public void Store_in_file()
        {
            const string entityFilename = @"testrepo\mypartition\myid.entity";
            Directory.CreateDirectory(@"testrepo\mypartition");
            File.Delete(entityFilename);

            var sut = new FilesystemEntityStore("testrepo");
            var mock = new MockStreamedStringAsEntity();

            sut.Store(mock);

            Assert.IsTrue(File.Exists(entityFilename));
            Assert.AreEqual(mock.Blob.Length, new FileInfo(entityFilename).Length);
        }


        [Test]
        public void Load_from_mem_stream()
        {
            var sut = new FilesystemEntityStore("testrepo");
            var mock = new MockStreamedStringAsEntity();
            var mem = new MemoryStream();

            sut.Store(mem, mock);

            mem.Seek(0, SeekOrigin.Begin);
            IStreamedEntity loaded = sut.Load(mock.Id, mock.Partition, mem);

            Assert.AreEqual(mock.Id, loaded.Id);
            Assert.AreEqual(mock.Partition, loaded.Partition);
            Assert.AreEqual(mock.Blob.Length, loaded.Blob.Length);
        }


        [Test]
        public void Load_from_file()
        {
            var sut = new FilesystemEntityStore("testrepo");
            var mock = new MockStreamedStringAsEntity();

            sut.Store(mock);
            IStreamedEntity loaded = sut.Load(mock.Id, mock.Partition);

            Assert.AreEqual(mock.Blob.Length, loaded.Blob.Length);
        }


        [Test]
        public void Delete_non_existing_entity()
        {
            var sut = new FilesystemEntityStore("testrepo");
            sut.Delete(Guid.NewGuid().ToString(), "mypartition");
        }


        [Test]
        public void Delete_existing_entity()
        {
            const string entityFilename = @"testrepo\mypartition\myid.entity";

            var sut = new FilesystemEntityStore("testrepo");
            var mock = new MockStreamedStringAsEntity();

            sut.Store(mock);
            Assert.IsTrue(File.Exists(entityFilename));

            sut.Delete(mock.Id, mock.Partition);
            Assert.IsFalse(File.Exists(entityFilename));
        }
    }
}
